package icegps.com.bhmap.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.SurfaceTexture;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.TextureView;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import icegps.com.bhmap.bean.MultipleEvaluatorHelp;
import icegps.com.bhmap.bean.TargetPoint;
import icegps.com.bhmap.drawhelp.AnimaHelp;
import icegps.com.bhmap.drawhelp.DrawLocation;
import icegps.com.bhmap.drawhelp.DrawRect;
import icegps.com.bhmap.drawhelp.MapController;

/**
 * Created by 111 on 2017/12/4.
 */

public class MapView extends TextureView implements TextureView.SurfaceTextureListener, IMapView {
    private final DrawLocation drawLocation;//绘制我的位置help类
    private final DrawRect drawRect;//绘制方块类
    private final GestureDetector gestureDetector;//手势操作
    private final ScaleGestureDetector scaleGestureDetector;//手势操作
    private volatile float translateX, translateY;//本次相对偏移量
    private volatile float px;//地图缩放时的偏移量
    private volatile float py;//地图缩放时的偏移量
    private volatile float multiple = 1.0f;//实时倍数
    private volatile float scaleEndMultiple = 1.0f;//缩放结束之后才赋值的倍数
    private volatile float rLength = 20.0f * multiple;//正方形边长
    private TargetPoint targetPoint;//目标点
    private final DrawUiThread drawUiThread;
    private volatile float locationMoveX;
    private volatile float locationMoveY;
    private CyclicBarrier cyclicBarrier;
    private MapController mapController;
    private Handler handler;
    private final ExecutorService executorService;

    public MapView(Context context, AttributeSet attrs) {
        super(context, attrs);
        executorService = Executors.newSingleThreadExecutor();
        cyclicBarrier = new CyclicBarrier(2);
        gestureDetector = new GestureDetector(context, simpleOnGestureListener);
        scaleGestureDetector = new ScaleGestureDetector(context, onScaleGestureListener);
        drawLocation = new DrawLocation(this);
        drawRect = new DrawRect(this);
        targetPoint = new TargetPoint();
        mapController = new MapController(MapView.this, cyclicBarrier);
        drawUiThread = new DrawUiThread();
        drawUiThread.start();
        setSurfaceTextureListener(this);
    }

    private void drawUI() {
        Canvas canvas = lockCanvas();
        try {
            canvas.drawColor(Color.parseColor("#a0a0a0"));
            //手势拖动画布
            canvas.translate(translateX - px, translateY - py);

            //位置点移动多少,画布就反向移动多少,始终保持位置点在中心
            canvas.translate(locationMoveX * multiple, locationMoveY * multiple);

            //画方块
            drawRect.drawRect(canvas);
            //画圆
            drawLocation.drawShape(canvas, targetPoint);

        } catch (Throwable throwable) {

            throwable.printStackTrace();

        } finally {
            unlockCanvasAndPost(canvas);
        }
    }

    public void setTargetPoint(TargetPoint targetPoint) {
        mapController.setTargetPoint(targetPoint);
    }


    @Override
    public boolean onTouchEvent(final MotionEvent event) {
        gestureDetector.onTouchEvent(event);
        scaleGestureDetector.onTouchEvent(event);

        return true;
    }
    //textureview被激活时
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        translateX = width / 2;
        translateY = height / 2;
        refUi();
    }

    /**
     * 位置移动
     *
     * @param targetPoint 目标位置
     * @param fraction    移动进度  0.0~1.0
     */
    @Override
    public void moveLocation(final TargetPoint targetPoint, final float fraction) {
        //更新原点位置
        this.targetPoint = targetPoint;

        //反向移动画布
        locationMoveX = (float) (-targetPoint.getPointX());
        locationMoveY = (float) (-targetPoint.getPointY());
        if (fraction == AnimaHelp.ANIMA_END) {
            try {
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
        refUi();
    }

    /**
     * 地图缩放
     *
     * @param multipleEvaluatorHelp 其中包括倍数/画布应该移动的x y
     */
    @Override
    public void scaleMap(final MultipleEvaluatorHelp multipleEvaluatorHelp, final float fraction) {

        multiple = multipleEvaluatorHelp.getMultiple();

        px = multipleEvaluatorHelp.getPx();

        py = multipleEvaluatorHelp.getPy();

        if (fraction == AnimaHelp.ANIMA_END) {
            translateXyAddPxPy();
        }
        refUi();
    }

    @Override
    public float getRLength() {
        return rLength;
    }

    @Override
    public float getScaleEndMultiple() {
        return scaleEndMultiple;
    }

    @Override
    public float getMultiple() {
        return multiple;
    }

    @Override
    public float getTranslateX() {
        return translateX;
    }

    @Override
    public float getTranslateY() {
        return translateY;
    }

    @Override
    public TargetPoint getTargetPoint() {
        return targetPoint;
    }

    @Override
    public MapController getMapController() {
        return mapController;
    }

    @Override
    public Context getActivity() {
        return getContext();
    }

    private void translateXyAddPxPy() {
        translateX -= px;
        translateY -= py;
        px = 0;
        py = 0;
    }

    //滑动,双击手势
    GestureDetector.SimpleOnGestureListener simpleOnGestureListener = new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onDoubleTap(MotionEvent e) {
            scaleEndMultiple *= 1.5f;
            mapController.setScale(e.getX(), e.getY(), multiple, 1.5f, true);
            return super.onDoubleTap(e);
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, final float distanceX, final float distanceY) {
            translateX -= distanceX;
            translateY -= distanceY;
            refUi();
            return super.onScroll(e1, e2, distanceX, distanceY);
        }

    };

    private void refUi() {
        handler.sendEmptyMessage(0);
    }

    //缩放手势
    ScaleGestureDetector.OnScaleGestureListener onScaleGestureListener = new ScaleGestureDetector.OnScaleGestureListener() {
        float focusX;
        float focusY;

        @Override
        public boolean onScale(final ScaleGestureDetector detector) {

            if (focusX == 0 && focusY == 0) {

                focusX = detector.getFocusX();

                focusY = detector.getFocusY();
            }

            mapController.setScale(focusX, focusY, multiple, detector.getScaleFactor(), false);

            return false;
        }

        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            return true;
        }

        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {
            focusY = 0;
            focusX = 0;
            translateXyAddPxPy();
            scaleEndMultiple *= detector.getScaleFactor();
        }
    };

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

    class DrawUiThread extends Thread {
        @SuppressLint("HandlerLeak")
        @Override
        public void run() {
            super.run();
            Looper.prepare();
            handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    drawUI();
                }
            };
            Looper.loop();
        }
    }
}
